package edu.ruc.cluster.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.io.OutputStream;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

/**
 * 2012-12-5
 * Abstract class for running interactive command including sudo.
 * Any class extends AbstractInteractiveCommand should override the abstract method interactProcess(String cmd)
 * When running sudo, just add "sudo" in your command, like "sudo adduser abc"
 * @author deke
 */
public abstract class AbstractInteractiveCommand {

	private JSch jsch = null;
	private Session session = null;
	private UserInfo userinfo = null;
	public Channel channel = null;
	
	@SuppressWarnings("unused")
	private String command = null;		
	private String passwd = null;
	private String host = null;
	private String user = null;
	
	public BufferedReader reader = null;
	public OutputStream writor = null;	
	public DefaultLogHandler logHandler = null;
	public Properties property = null;	
	
	abstract public void interactProcess(String cmd);
	public void setProperty(Map<String, String> info){		
		if(info.isEmpty())
			return;
		Iterator<String> iter = info.keySet().iterator();
		while(iter.hasNext()){
			String key = iter.next();
			property.setProperty(key, info.get(key));		
		}		
	}
	public AbstractInteractiveCommand(String hostt, String passwd){
		
		logHandler = DefaultLogHandler.getInstance();
		property = new Properties();
		
		this.passwd = passwd;
		this.user = hostt.substring(0, hostt.indexOf('@'));
	    this.host = hostt.substring(hostt.indexOf('@') + 1);
	    
	    jsch = new JSch();
		userinfo = new MyUserInfo(passwd);
	
		try{				 
		    session = jsch.getSession(user, host, 22);
		    session.setUserInfo(userinfo);
		    session.connect();		    
					    
		    channel = (ChannelShell)session.openChannel("shell");
			writor = channel.getOutputStream();
		    reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));				
			channel.connect();			    			    
		    System.out.println("connected to " + user + "@" + host);
		    
		}catch(JSchException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	public String getPasswd(){
		return passwd;
	}
	public String getHost(){
		return this.host;
	}
	public String getUser(){
		return this.user;
	}
		  // Used in channel = session.openChannel("exec"):[reference com.jcraft.jsch.example.Sudo.java]
		  //		channel.setPty(true);
	      //		channel.setCommand("sudo -S -p '' " + command);
		  // man sudo
	      //   -S  The -S (stdin) option causes sudo to read the password from the
	      //       standard input instead of the terminal device.
	      //   -p  The -p (prompt) option allows you to override the default
	      //       password prompt and use a custom one.
		
	public void dealcmd(String cmd){
		interactProcess(cmd);
		System.out.println("going to close...");
		close();
	}    
	
	private void close(){
		try{
			writor.close();
			reader.close();
			channel.disconnect();
			session.disconnect();
			
		}catch(IOException e){
			logHandler.error(this.getClass().getSimpleName(), e);
		}
	}
}
